﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="TableWrapper.cs" company="Data Ductus Malmö">
//   (c) 2010 - 2012 Data Ductus Malmö AB
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace DataDuctus.Snmp.Persistor.Core.Agent.Internal
{
  using System.Collections.Generic;
  using System.Reflection;

  using DataDuctus.Snmp.Persistor.Core.MetaData;

  using Lextm.SharpSnmpLib.Pipeline;

  /// <summary>
  /// The table wrapper.
  /// </summary>
  internal class TableWrapper : TableObject
  {
    #region Fields

    /// <summary>
    /// The accessor.
    /// </summary>
    private readonly AccessorMeta accessor;

    /// <summary>
    /// The clz meta.
    /// </summary>
    private readonly ClassMeta clzMeta;

    /// <summary>
    /// The instance.
    /// </summary>
    private readonly object instance;

    #endregion

    #region Constructors and Destructors

    /// <summary>
    /// Initializes a new instance of the <see cref="TableWrapper"/> class.
    /// </summary>
    /// <param name="clzMeta">
    /// The clz meta.
    /// </param>
    /// <param name="accessor">
    /// The accessor.
    /// </param>
    /// <param name="instance">
    /// The instance.
    /// </param>
    internal TableWrapper(ClassMeta clzMeta, AccessorMeta accessor, object instance)
    {
      this.clzMeta = clzMeta;
      this.accessor = accessor;
      this.instance = instance;
    }

    #endregion

    #region Properties

    /// <summary>
    /// Gets the objects.
    /// </summary>
    protected override IEnumerable<ScalarObject> Objects
    {
      get
      {
        List<object> data = GetDataList(this.accessor, this.instance);

        if (0 == data.Count)
        {
          return null;
        }

        var list = new List<ScalarObject>();

        foreach (object obj in data)
        {
          list.AddRange(ScalarWrapper.CreateWrappers(this.clzMeta, obj));
        }

        return list;
      }
    }

    #endregion

    #region Methods

    /// <summary>
    /// The get data.
    /// </summary>
    /// <param name="accessor">
    /// The accessor.
    /// </param>
    /// <param name="instance">
    /// The instance.
    /// </param>
    /// <returns>
    /// The System.Object.
    /// </returns>
    private static object GetData(AccessorMeta accessor, object instance)
    {
      var pinfo = accessor.Accessor as PropertyInfo;

      if (null != pinfo)
      {
        return pinfo.GetValue(instance, null);
      }

      return ((MethodInfo)accessor.Accessor).Invoke(instance, null);
    }

    /// <summary>
    /// The get data list.
    /// </summary>
    /// <param name="accessor">
    /// The accessor.
    /// </param>
    /// <param name="instance">
    /// The instance.
    /// </param>
    /// <returns>
    /// The System.Collections.Generic.List`1[T -&gt; System.Object].
    /// </returns>
    private static List<object> GetDataList(AccessorMeta accessor, object instance)
    {
      var list = new List<object>();

      object data = GetData(accessor, instance);

      if (null != data)
      {
        list.Add(data);
      }

      return list;
    }

    #endregion
  }
}